#include "movemaker.h"

// main method for moving a piece (doMove)
void MoveMaker::doMove(Move move) {
    // adjust gameline
    board_.gameLine.gameMove.at(board_.gameLine.plyAhead) = move;
    board_.gameLine.enPassantSquare.at(board_.gameLine.plyAhead) = board_.enPassantSquare;
    board_.gameLine.wCanCastle00.at(board_.gameLine.plyAhead) = board_.wCanCastle00;
    board_.gameLine.wCanCastle000.at(board_.gameLine.plyAhead) = board_.wCanCastle000;
    board_.gameLine.bCanCastle00.at(board_.gameLine.plyAhead) = board_.bCanCastle00;
    board_.gameLine.bCanCastle000.at(board_.gameLine.plyAhead) = board_.bCanCastle000;
    board_.gameLine.plyAhead++;

    switch (move.piece)
    {
        case WHITE_KING:
           // castling foreit
           board_.wCanCastle00 = board_.wCanCastle000 = false;
           board_.wK         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.wPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           testForCapture(WHITE_TO_MOVE,move); // and sets occupied squares!

           if (move.castling == WHITE_00_CASTLING_MOVE) {
               board_.wR              ^= (Bitutils::Bit(F1) | Bitutils::Bit(H1)); // move rook
               board_.wPieces         ^= (Bitutils::Bit(F1) | Bitutils::Bit(H1));
               board_.occupiedSquares ^= (Bitutils::Bit(F1) | Bitutils::Bit(H1));
               break;
           }
           if (move.castling == WHITE_000_CASTLING_MOVE) {
               board_.wR              ^= (Bitutils::Bit(A1) | Bitutils::Bit(D1)); // move rook
               board_.wPieces         ^= (Bitutils::Bit(A1) | Bitutils::Bit(D1));
               board_.occupiedSquares ^= (Bitutils::Bit(A1) | Bitutils::Bit(D1));
               break;
           }
           break;

        case WHITE_KNIGHT:
           board_.wN         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.wPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           testForCapture(WHITE_TO_MOVE,move);
           break;

        case WHITE_ROOK:
           // castling foreit on one side
           if (move.from == 0) board_.wCanCastle000 = false;
           if (move.from == 7) board_.wCanCastle00 = false;

           board_.wR         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.wPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           testForCapture(WHITE_TO_MOVE,move);
           break;

        case WHITE_BISHOP:
           board_.wB         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.wPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           testForCapture(WHITE_TO_MOVE,move);
           break;

        case WHITE_QUEEN:
           board_.wQ         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.wPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           testForCapture(WHITE_TO_MOVE,move);
           break;

        case WHITE_PAWN:
           board_.wP         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.wPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));

           // set en-passant square on double move from starting line
           if (ISIN(move.from,8,15) && ISIN(move.to,24,31)) {
               board_.enPassantSquare = move.to - 8;
           }

           // special case : capture en-passant?
           if (move.to == board_.enPassantSquare) {
               // simple move, and....
               board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
               // on square (move.to-8) we find the black pawn to be removed
               board_.occupiedSquares ^= (Bitutils::Bit(move.to-8));
               board_.bP              ^= (Bitutils::Bit(move.to-8));
               board_.bPieces         ^= (Bitutils::Bit(move.to-8));
               board_.material += PAWN_VALUE;
               board_.enPassantSquare = -1;
               break;
           }
           testForCapture(WHITE_TO_MOVE,move);

           if (move.promotion == WHITE_QUEEN) {
               board_.wP ^= (Bitutils::Bit(move.to)); // remove white pawn and
               board_.wQ ^= (Bitutils::Bit(move.to)); // add a queen to board (occupied squares unchanged)
               board_.material -= PAWN_VALUE;
               board_.material += QUEEN_VALUE;
               break;
           }
           if (move.promotion == WHITE_ROOK) {
               board_.wP ^= (Bitutils::Bit(move.to)); // remove white pawn and
               board_.wR ^= (Bitutils::Bit(move.to)); // add a rook to board (occupied squares unchanged)
               board_.material -= PAWN_VALUE;
               board_.material += ROOK_VALUE;
               break;
           }
           if (move.promotion == WHITE_BISHOP) {
               board_.wP ^= (Bitutils::Bit(move.to)); // remove white pawn and
               board_.wB ^= (Bitutils::Bit(move.to)); // add a bishop to board (occupied squares unchanged)
               board_.material -= PAWN_VALUE;
               board_.material += BISHOP_VALUE;
               break;
           }
           if (move.promotion == WHITE_KNIGHT) {
               board_.wP ^= (Bitutils::Bit(move.to)); // remove white pawn and
               board_.wN ^= (Bitutils::Bit(move.to)); // add a knight to board (occupied squares unchanged)
               board_.material -= PAWN_VALUE;
               board_.material += KNIGHT_VALUE;
               break;
           }
           break;

        case BLACK_KING:
           // castling foreit
           board_.bCanCastle00 = board_.bCanCastle000 = false;
           board_.bK         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.bPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           testForCapture(BLACK_TO_MOVE,move);

           if (move.castling == BLACK_00_CASTLING_MOVE) {
               board_.bR              ^= (Bitutils::Bit(F8) | Bitutils::Bit(H8)); // move rook
               board_.bPieces         ^= (Bitutils::Bit(F8) | Bitutils::Bit(H8));
               board_.occupiedSquares ^= (Bitutils::Bit(F8) | Bitutils::Bit(H8));
               break;
           }
           if (move.castling == BLACK_000_CASTLING_MOVE) {
               board_.bR              ^= (Bitutils::Bit(A8) | Bitutils::Bit(D8)); // move rook
               board_.bPieces         ^= (Bitutils::Bit(A8) | Bitutils::Bit(D8));
               board_.occupiedSquares ^= (Bitutils::Bit(A8) | Bitutils::Bit(D8));
               break;
           }
           break;

        case BLACK_KNIGHT:
           board_.bN         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.bPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           testForCapture(BLACK_TO_MOVE,move);
           break;

        case BLACK_ROOK:
           // castling foreit on one side
           if (move.from == 56) board_.bCanCastle000 = false;
           if (move.from == 63) board_.bCanCastle00 = false;

           board_.bR         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.bPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           testForCapture(BLACK_TO_MOVE,move);
           break;

        case BLACK_BISHOP:
           board_.bB         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.bPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           testForCapture(BLACK_TO_MOVE,move);
           break;

        case BLACK_QUEEN:
           board_.bQ         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.bPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           testForCapture(BLACK_TO_MOVE,move);
           break;

        case BLACK_PAWN:
           board_.bP         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.bPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));

           // set en-passant square on double move from starting line
           if (ISIN(move.from,48,55) && ISIN(move.to,32,39)) {
               board_.enPassantSquare = move.to + 8;
           }

           // special case : capture en-passant?
           if (move.to == board_.enPassantSquare) {
               // simple move, and....
               board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
               // on square (move.to+8) we find the white pawn to be removed
               board_.occupiedSquares ^= (Bitutils::Bit(move.to+8));
               board_.wP              ^= (Bitutils::Bit(move.to+8));
               board_.wPieces         ^= (Bitutils::Bit(move.to+8));
               board_.material -= PAWN_VALUE;
               board_.enPassantSquare = -1;
               break;
           }
           testForCapture(BLACK_TO_MOVE,move);

           if (move.promotion == BLACK_QUEEN) {
               board_.bP ^= (Bitutils::Bit(move.to)); // remove BLACK pawn and
               board_.bQ ^= (Bitutils::Bit(move.to)); // add a queen to board (occupied squares unchanged)
               board_.material += PAWN_VALUE;
               board_.material -= QUEEN_VALUE;
               break;
           }
           if (move.promotion == BLACK_ROOK) {
               board_.bP ^= (Bitutils::Bit(move.to)); // remove BLACK pawn and
               board_.bR ^= (Bitutils::Bit(move.to)); // add a rook to board (occupied squares unchanged)
               board_.material += PAWN_VALUE;
               board_.material -= ROOK_VALUE;
               break;
           }
           if (move.promotion == BLACK_BISHOP) {
               board_.bP ^= (Bitutils::Bit(move.to)); // remove BLACK pawn and
               board_.bB ^= (Bitutils::Bit(move.to)); // add a bishop to board (occupied squares unchanged)
               board_.material += PAWN_VALUE;
               board_.material -= BISHOP_VALUE;
               break;
           }
           if (move.promotion == BLACK_KNIGHT) {
               board_.bP ^= (Bitutils::Bit(move.to)); // remove BLACK pawn and
               board_.bN ^= (Bitutils::Bit(move.to)); // add a knight to board (occupied squares unchanged)
               board_.material += PAWN_VALUE;
               board_.material -= KNIGHT_VALUE;
               break;
           }
           break;
    }
}


// test for a capture move _ TODO this SETS occupied squares - could transfer to main routine - would seem more concise
void MoveMaker::testForCapture(bool sideToMove, Move & move) {
    if (sideToMove == WHITE_TO_MOVE)
        if (board_.bPieces & Bitutils::Bit(move.to)) // test for capture move?
        {
            // so do a capture move
            doCapture(WHITE_TO_MOVE, move.to);
            // only remove piece on from field
            board_.occupiedSquares ^= Bitutils::Bit(move.from);
        }
        else // no capture -> simple move
            board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));

    if (sideToMove == BLACK_TO_MOVE)
        if (board_.wPieces & Bitutils::Bit(move.to)) // test for capture move?
        {
            // so do a capture move
            doCapture(BLACK_TO_MOVE, move.to);
            // only remove piece on from field
            board_.occupiedSquares ^= Bitutils::Bit(move.from);
        }
        else // no capture -> simple move
            board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));

}

// do capture move on bitboards
void MoveMaker::doCapture(bool sideToMove, size_t to) {

    if (sideToMove == WHITE_TO_MOVE) {
        // pawn is most probable
        if (board_.bP & Bitutils::Bit(to)) {
            // adjust material on board
            board_.material += PAWN_VALUE;
            // adjust bitboards
            board_.bP      ^= Bitutils::Bit(to);
            board_.bPieces ^= Bitutils::Bit(to);
        }
        else if (board_.bN & Bitutils::Bit(to)) {
                // adjust material on board
                board_.material += KNIGHT_VALUE;
                // adjust bitboards
                board_.bN      ^= Bitutils::Bit(to);
                board_.bPieces ^= Bitutils::Bit(to);
             } else if (board_.bB & Bitutils::Bit(to)) {
                        // adjust material on board
                        board_.material += BISHOP_VALUE;
                        // adjust bitboards
                        board_.bB      ^= Bitutils::Bit(to);
                        board_.bPieces ^= Bitutils::Bit(to);
                    } else if (board_.bR & Bitutils::Bit(to)) {
                                // adjust material on board
                                board_.material += ROOK_VALUE;
                                // adjust bitboards
                                board_.bR      ^= Bitutils::Bit(to);
                                board_.bPieces ^= Bitutils::Bit(to);
                           } else if (board_.bQ & Bitutils::Bit(to)) {
                                        // adjust material on board
                                        board_.material += QUEEN_VALUE;
                                        // adjust bitboards
                                        board_.bQ      ^= Bitutils::Bit(to);
                                        board_.bPieces ^= Bitutils::Bit(to);
                                  }
                                  else if (board_.bK & Bitutils::Bit(to)) {
                                               // adjust material on board
                                               board_.material += KING_VALUE;
                                               // adjust bitboards
                                               board_.bK      ^= Bitutils::Bit(to);
                                               board_.bPieces ^= Bitutils::Bit(to);
                                               qDebug() << "BLACK KING CAPTURED";
                                         }
    }

    if (sideToMove == BLACK_TO_MOVE) {
        // pawn is most probable
        if (board_.wP & Bitutils::Bit(to)) {
            // adjust material on board
            board_.material -= PAWN_VALUE;
            // adjust bitboards
            board_.wP      ^= Bitutils::Bit(to);
            board_.wPieces ^= Bitutils::Bit(to);
        }
        else if (board_.wN & Bitutils::Bit(to)) {
                // adjust material on board
                board_.material -= KNIGHT_VALUE;
                // adjust bitboards
                board_.wN      ^= Bitutils::Bit(to);
                board_.wPieces ^= Bitutils::Bit(to);
             } else if (board_.wB & Bitutils::Bit(to)) {
                        // adjust material on board
                        board_.material -= BISHOP_VALUE;
                        // adjust bitboards
                        board_.wB      ^= Bitutils::Bit(to);
                        board_.wPieces ^= Bitutils::Bit(to);
                    } else if (board_.wR & Bitutils::Bit(to)) {
                                // adjust material on board
                                board_.material -= ROOK_VALUE;
                                // adjust bitboards
                                board_.wR      ^= Bitutils::Bit(to);
                                board_.wPieces ^= Bitutils::Bit(to);
                           } else if (board_.wQ & Bitutils::Bit(to)) {
                                        // adjust material on board
                                        board_.material -= QUEEN_VALUE;
                                        // adjust bitboards
                                        board_.wQ      ^= Bitutils::Bit(to);
                                        board_.wPieces ^= Bitutils::Bit(to);
                                  }
                                  else if (board_.wK & Bitutils::Bit(to)) {
                                             // adjust material on board
                                             board_.material -= KING_VALUE;
                                             // adjust bitboards
                                             board_.wK      ^= Bitutils::Bit(to);
                                             board_.wPieces ^= Bitutils::Bit(to);
                                             qDebug() << "WHITE KING CAPTURED";
                                       }
    }

}

// undo capture move on bitboards
void MoveMaker::undoCapture(size_t captured, size_t to) {
    // deals with all captures, except en-passant

    switch (captured)
    {
           case 1: // white pawn:
              board_.wP       ^= Bitutils::Bit(to);
              board_.wPieces  ^= Bitutils::Bit(to);
              board_.material += PAWN_VALUE;
              break;

           case 2: // white king:
              board_.wK       ^= Bitutils::Bit(to);
              board_.wPieces  ^= Bitutils::Bit(to);
              board_.material += KING_VALUE;
              break;

           case 3: // white knight:
              board_.wN       ^= Bitutils::Bit(to);
              board_.wPieces  ^= Bitutils::Bit(to);
              board_.material += KNIGHT_VALUE;
              break;

           case 5: // white bishop:
              board_.wB       ^= Bitutils::Bit(to);
              board_.wPieces  ^= Bitutils::Bit(to);
              board_.material += BISHOP_VALUE;
              break;

           case 6: // white rook:
              board_.wR       ^= Bitutils::Bit(to);
              board_.wPieces  ^= Bitutils::Bit(to);
              board_.material += ROOK_VALUE;
              break;

           case 7: // white queen:
              board_.wQ       ^= Bitutils::Bit(to);
              board_.wPieces  ^= Bitutils::Bit(to);
              board_.material += QUEEN_VALUE;
              break;

           case 9: // black pawn:
                board_.bP       ^= Bitutils::Bit(to);
                board_.bPieces  ^= Bitutils::Bit(to);
                board_.material -= PAWN_VALUE;
                break;

           case 10: // black king:
                board_.bK       ^= Bitutils::Bit(to);
                board_.bPieces  ^= Bitutils::Bit(to);
                board_.material -= KING_VALUE;
                break;

           case 11: // black knight:
                board_.bN       ^= Bitutils::Bit(to);
                board_.bPieces  ^= Bitutils::Bit(to);
                board_.material -= KNIGHT_VALUE;
                break;

           case 13: // black bishop:
                board_.bB       ^= Bitutils::Bit(to);
                board_.bPieces  ^= Bitutils::Bit(to);
                board_.material -= BISHOP_VALUE;
                break;

           case 14: // black rook:
                board_.bR       ^= Bitutils::Bit(to);
                board_.bPieces  ^= Bitutils::Bit(to);
                board_.material -= ROOK_VALUE;
                break;

           case 15: // black queen:
                board_.bQ       ^= Bitutils::Bit(to);
                board_.bPieces  ^= Bitutils::Bit(to);
                board_.material -= QUEEN_VALUE;
                break;
    }
}

void MoveMaker::undoMove(Move move) {
    // restore board info status for ply-1
    board_.gameLine.plyAhead--;
    board_.enPassantSquare = board_.gameLine.enPassantSquare.at(board_.gameLine.plyAhead);
    board_.wCanCastle00 = board_.gameLine.wCanCastle00.at(board_.gameLine.plyAhead);
    board_.wCanCastle000 = board_.gameLine.wCanCastle000.at(board_.gameLine.plyAhead);
    board_.bCanCastle00 = board_.gameLine.bCanCastle00.at(board_.gameLine.plyAhead);
    board_.bCanCastle000 = board_.gameLine.bCanCastle000.at(board_.gameLine.plyAhead);

    switch (move.piece)
    {
        case WHITE_KING:
            board_.wK         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            board_.wPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            // set back castling (flags for old ply are set back from gameline[ply-1] object)
            if (move.castling == WHITE_00_CASTLING_MOVE) {
                board_.wR              ^= (Bitutils::Bit(F1) | Bitutils::Bit(H1));
                board_.wPieces         ^= (Bitutils::Bit(F1) | Bitutils::Bit(H1));
                board_.occupiedSquares ^= (Bitutils::Bit(F1) | Bitutils::Bit(H1));
            }
            if (move.castling == WHITE_000_CASTLING_MOVE) {
                board_.wR              ^= (Bitutils::Bit(A1) | Bitutils::Bit(D1));
                board_.wPieces         ^= (Bitutils::Bit(A1) | Bitutils::Bit(D1));
                board_.occupiedSquares ^= (Bitutils::Bit(A1) | Bitutils::Bit(D1));
            }

            if (move.captured)
            {
                  undoCapture(move.captured, move.to);
                  board_.occupiedSquares ^= Bitutils::Bit(move.from);
            }
            else board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            break;

        case WHITE_KNIGHT:
           board_.wN         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.wPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           if (move.captured)
           {
                 undoCapture(move.captured, move.to);
                 board_.occupiedSquares ^= Bitutils::Bit(move.from);
           }
           else board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           break;

        case WHITE_ROOK:
            board_.wR         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            board_.wPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            if (move.captured)
            {
                  undoCapture(move.captured, move.to);
                  board_.occupiedSquares ^= Bitutils::Bit(move.from);
            }
            else board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            break;

        case WHITE_BISHOP:
            board_.wB         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            board_.wPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            if (move.captured)
            {
                  undoCapture(move.captured, move.to);
                  board_.occupiedSquares ^= Bitutils::Bit(move.from);
            }
            else board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            break;

        case WHITE_QUEEN:
            board_.wQ         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            board_.wPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            if (move.captured)
            {
                  undoCapture(move.captured, move.to);
                  board_.occupiedSquares ^= Bitutils::Bit(move.from);
            }
            else board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            break;

        case WHITE_PAWN:
            board_.wP         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            board_.wPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));

            // undo promotion
            if (move.promotion > 0) {
                 board_.wP ^= (Bitutils::Bit(move.to)); // double remove on pawn!
                 board_.material += PAWN_VALUE;
                 if (move.promotion == WHITE_QUEEN) {
                     board_.wQ ^= (Bitutils::Bit(move.to));
                     board_.material -= QUEEN_VALUE;
                 }
                 if (move.promotion == WHITE_ROOK) {
                     board_.wR ^= (Bitutils::Bit(move.to));
                     board_.material -= ROOK_VALUE;
                 }
                 if (move.promotion == WHITE_BISHOP) {
                     board_.wB ^= (Bitutils::Bit(move.to));
                     board_.material -= BISHOP_VALUE;
                 }
                 if (move.promotion == WHITE_KNIGHT) {
                     board_.wN ^= (Bitutils::Bit(move.to));
                     board_.material -= KNIGHT_VALUE;
                 }
            }

            // did we do a move to an en-passant square?
            if (board_.enPassantSquare == move.to)
            {
                  // add black pawn to board again
                  board_.bP         ^= Bitutils::Bit(move.to-8);
                  board_.bPieces    ^= Bitutils::Bit(move.to-8);
                  board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to)
                                             | Bitutils::Bit(move.to-8));
                  board_.material -= PAWN_VALUE;
            }
            else if (move.captured) {
                    undoCapture(move.captured, move.to);
                    board_.occupiedSquares ^= Bitutils::Bit(move.from);
                 }
                 else board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            break;

        case BLACK_KING:
            board_.bK         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            board_.bPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            // set back castling (flags for old ply are set back from gameline[ply-1] object)
            if (move.castling == BLACK_00_CASTLING_MOVE) {
                board_.bR              ^= (Bitutils::Bit(F8) | Bitutils::Bit(H8));
                board_.bPieces         ^= (Bitutils::Bit(F8) | Bitutils::Bit(H8));
                board_.occupiedSquares ^= (Bitutils::Bit(F8) | Bitutils::Bit(H8));
            }
            if (move.castling == BLACK_000_CASTLING_MOVE) {
                board_.bR              ^= (Bitutils::Bit(A8) | Bitutils::Bit(D8));
                board_.bPieces         ^= (Bitutils::Bit(A8) | Bitutils::Bit(D8));
                board_.occupiedSquares ^= (Bitutils::Bit(A8) | Bitutils::Bit(D8));
            }

            if (move.captured)
            {
                  undoCapture(move.captured, move.to);
                  board_.occupiedSquares ^= Bitutils::Bit(move.from);
            }
            else board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            break;

        case BLACK_KNIGHT:
            board_.bN         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            board_.bPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            if (move.captured)
            {
                  undoCapture(move.captured, move.to);
                  board_.occupiedSquares ^= Bitutils::Bit(move.from);
            }
            else board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            break;

        case BLACK_ROOK:
           board_.bR         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.bPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           if (move.captured)
           {
                 undoCapture(move.captured, move.to);
                 board_.occupiedSquares ^= Bitutils::Bit(move.from);
           }
           else board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           break;

        case BLACK_BISHOP:
            board_.bB         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            board_.bPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            if (move.captured)
            {
                  undoCapture(move.captured, move.to);
                  board_.occupiedSquares ^= Bitutils::Bit(move.from);
            }
            else board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            break;

        case BLACK_QUEEN:
           board_.bQ         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           board_.bPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           if (move.captured)
           {
                 undoCapture(move.captured, move.to);
                 board_.occupiedSquares ^= Bitutils::Bit(move.from);
           }
           else board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
           break;

        case BLACK_PAWN:
            board_.bP         ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            board_.bPieces    ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));

            // undo promotion
            if (move.promotion > 0) {
                 board_.bP ^= (Bitutils::Bit(move.to)); // double remove on pawn!
                 board_.material -= PAWN_VALUE;
                 if (move.promotion == BLACK_QUEEN) {
                     board_.bQ ^= (Bitutils::Bit(move.to));
                     board_.material += QUEEN_VALUE;
                 }
                 if (move.promotion == BLACK_ROOK) {
                     board_.bR ^= (Bitutils::Bit(move.to));
                     board_.material += ROOK_VALUE;
                 }
                 if (move.promotion == BLACK_BISHOP) {
                     board_.bB ^= (Bitutils::Bit(move.to));
                     board_.material += BISHOP_VALUE;
                 }
                 if (move.promotion == BLACK_KNIGHT) {
                     board_.bN ^= (Bitutils::Bit(move.to));
                     board_.material += KNIGHT_VALUE;
                 }
            }

            // did we do a move to an en-passant square?
            if (board_.enPassantSquare == move.to)
            {
                  // add white pawn to board again
                  board_.wP         ^= Bitutils::Bit(move.to+8);
                  board_.wPieces    ^= Bitutils::Bit(move.to+8);
                  board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to)
                                             | Bitutils::Bit(move.to+8));
                  board_.material += PAWN_VALUE;
            }
            else if (move.captured) {
                    undoCapture(move.captured, move.to);
                    board_.occupiedSquares ^= Bitutils::Bit(move.from);
                 }
                 else board_.occupiedSquares ^= (Bitutils::Bit(move.from) | Bitutils::Bit(move.to));
            break;
    }


}

